Jx.declare('Jx.system.Application', {

	$extend: 'Jx.Base',

	$requires: [ 'Jx.data.Collection', 'Jx.platform.Manager' ],

	$accessors: {

		platform: 'browser'

	},

	$actions: [

		'createController',

		'createModel',

		'createView',

		'initialize',

		'run'

	],

	$shortcuts: {

		'Jx': {

			'createApplication': 'create'

		}

	},

	$static: {

		'create': function(name, declaration){

			var path, callback, ns, shortcuts;

			if (Jx.isString(name, true)){

				path = name+'.Application';

				if (!Jx.isObject(declaration)){

					declaration = {};

				}

				ns = Jx.ns(name);

				//-- set it to callback after my setup
				if (declaration.hasOwnProperty('$callback')){

					if (Jx.isFunction(callback = declaration['$callback'])){

						Jx.onDeclare( path, callback );

					}

					delete declaration['$callback'];

				}

				//-- update shortcuts
				if (!declaration.hasOwnProperty('$shortcuts') ||

					!Jx.isObject(declaration.$shortcuts)

				){

					declaration.$shortcuts = {};

				}

				shortcuts = declaration.$shortcuts;

				if (!shortcuts.hasOwnProperty(name) ||

					!Jx.isObject(shortcuts[name])

				){

					shortcuts[name] = {};

				}

				Jx.assignIf(shortcuts[name], {

					'createController': 'createController',

					'createView': 'createView',

					'createModel': 'createModel'

				});

				Jx.declare( path,

					Jx.assign({

						$singleton: true,

						$extend: this.$name,

						ns: name,

						//-- setup after declaring application
						$callback: function(Class, Base, instance){

							var prefix = instance.ns;

							//-- setup namespaces
							Jx.ns(

								prefix+'.control',

								prefix+'.model',

								prefix+'.view'

							);

							//-- initialize instance
							instance.initialize();

							instance.run();

						}

					}, declaration)

				);

			}

		}

	},

	ns: 'Undefined_Application',

	running: false,

	shortcuts: [

		'createController',

		'createModel',

		'createView'

	],

	components: null,

	dataSources: null,

	constructor: function(){

		this.components = Jx.instantiate('Jx.data.Collection');

		this.platform( this.platform() );

		this.$super(arguments);

	},

	initializeCache: function(cache){

		this.$super(arguments);

		Jx.each( cache, function(n, v, o){

			var camelized = n.charAt(0).toUpperCase()+n.substring(1, n.length),

				allow = 'allowSet'+camelized;

			//-- set
			if (allow in this){

				this[n](v);

			}


		}, this);

	},

	onSetPlatform: function(operation){

		this.set('platform', operation.value);

	},

	onCreateController: function(){

		this.declareApplicationClass.apply(this, arguments);

	},

	onCreateModel: function(){

		this.declareApplicationClass.apply(this, arguments);

	},

	onCreateView: function(){

		this.declareApplicationClass.apply(this, arguments);

	},

	onDispatch: function(operation){

		this.$super(arguments);


		//-- if not stopped
		if (operation.returnValue !== false){




		}

	},

	allowCreateController: function(operation){

		operation.create = 'Controller';

		return this.validateCreateApplicationClass.apply(this,
			
			['controller'].concat(
				
				Array.prototype.slice.call(arguments)
			
			)
			
		);

	},

	allowCreateModel: function(operation){

		operation.create = 'Model';

		return this.validateCreateApplicationClass.apply(this,
			
			['model'].concat(
				
				Array.prototype.slice.call(arguments)
			
			)
			
		);

	},

	allowCreateView: function(operation){

		operation.create = 'View';

		return this.validateCreateApplicationClass.apply(this,
			
			['view'].concat(
				
				Array.prototype.slice.call(arguments)
			
			)
			
		);

	},

	allowRun: function(operation){

		//-- check platform if capable
		var platform = this.platform();

		return !this.running &&

			!!platform &&

			platform.capable;

	},

	allowSetPlatform: function(operation, platform){

		var Mgr = Jx.platform.Manager,

			result = false;

		if (Jx.isString(platform, true)){

			platform = Mgr.get(platform) || Mgr.create(platform);

		}

		if ( Jx.instanceOf( platform, Mgr.baseType() ) ){

			result = operation.value = platform;

		} else {

			this.set('platform', undefined);

		}

		return result;

	},

	validateCreateApplicationClass: function(appNs, operation, name){

		var allow = Jx.isString(name, true);

		if (allow){

			operation.name = this.ns + '.' + appNs + '.' + name;

			operation.args = Array.prototype.slice.call(arguments, 3);

		}

		return allow;

	},

	declareApplicationClass: function(operation){

		var target = operation.create;

		Jx[ 'create' + target ].apply( Jx,

			[operation.name].concat(

				operation.args

			)

		);


	}




});
